package com.pochoF1.controller;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.pochoF1.enums.Sesiones;
import com.pochoF1.exceptions.DescargarFiaException;
import com.pochoF1.exceptions.DescargarFormulaOneException;
import com.pochoF1.exceptions.DescargarFormulaOneParsingException;
import com.pochoF1.exceptions.NoFileFiaException;
import com.pochoF1.model.Piloto;
import com.pochoF1.model.ResultRace;
import com.pochoF1.utils.LeerFIA;
import com.pochoF1.utils.LeerPDF;
import com.pochoF1.utils.ObtenerDatosCarrera;
import com.pochoF1.xml.Season;

@Controller
@SuppressWarnings("unchecked")
public class RacesController {

	private static Logger log = LoggerFactory.getLogger(RacesController.class);
	private static String pagina = "index";

	@RequestMapping(value = "/showRaces", method = RequestMethod.GET)
	public String showRaces(Model model, HttpServletRequest request, HttpServletResponse response) {
		Boolean errorSeason = false;
		HttpSession session = request.getSession();
		Season season = (Season) session.getAttribute("season");
		if (session.getAttribute("raceRound") != null)
			session.removeAttribute("raceRound");
		if (session.getAttribute("raceYear") != null)
			session.removeAttribute("raceYear");
		if (session.getAttribute("raceName") != null)
			session.removeAttribute("raceName");
		if (session.getAttribute("raceId") != null)
			session.removeAttribute("raceId");
		
		String raceYear = request.getParameter("raceYear");
		try {
			if (season == null) {
				season = ObtenerDatosCarrera.obtenerDatosTemporada();
				model.addAttribute("season", season);
				model.addAttribute("raceYear",raceYear==null?Calendar.getInstance().get(Calendar.YEAR):raceYear);
				session.setAttribute("season", season);
			} else {
				model.addAttribute("season", season);
				model.addAttribute("raceYear",raceYear==null?Calendar.getInstance().get(Calendar.YEAR):raceYear);
			}
		} catch (Exception e) {
			log.error(e.getMessage(), e);
			errorSeason = true;
		}

		model.addAttribute("errorSeason", errorSeason);
		return "showRaces";
	}

	@RequestMapping(value = "/showRaces", method = RequestMethod.POST)
	public String submitShowRacesForm(Model model, HttpServletRequest request, HttpServletResponse response) {
		HttpSession session = request.getSession();

		String raceRound = request.getParameter("raceRound");
		String raceYear = request.getParameter("raceYear");
		String raceName = request.getParameter("raceName");
		String raceId = request.getParameter("raceId");

		session.setAttribute("raceRound", raceRound);
		session.setAttribute("raceYear", raceYear);
		session.setAttribute("raceName", raceName);
		session.setAttribute("raceId", raceId);

		model.addAttribute("raceRound", raceRound);
		model.addAttribute("raceYear", raceYear);
		model.addAttribute("raceName", raceName);
		model.addAttribute("raceId", raceId);

		return "raceInfo";
	}

	@RequestMapping(value = "/raceInfo", method = RequestMethod.POST)
	public String submitRaceInfoForm(Model model, HttpServletRequest request, HttpServletResponse response) {
		HttpSession session = request.getSession();

		HashMap<String, Object> hashSesionLista = (HashMap<String, Object>) request.getSession().getAttribute("HASHSESIONRESULTADO");
		if (session.getAttribute("HASHPILOTOS") != null)
			session.removeAttribute("HASHPILOTOS");
		if (session.getAttribute("LISTAPILOTOS") != null)
			session.removeAttribute("LISTAPILOTOS");

		String idSesion = request.getParameter("session");
		String raceRound = session.getAttribute("raceRound")!=null?session.getAttribute("raceRound").toString():"";
		String raceYear = session.getAttribute("raceYear")!=null?session.getAttribute("raceYear").toString():"";
		String raceName = session.getAttribute("raceName")!=null?session.getAttribute("raceName").toString():"";
		String raceId = session.getAttribute("raceId")!=null?session.getAttribute("raceId").toString():"";
		
		model.addAttribute("session",idSesion);
		model.addAttribute("raceRound",raceRound);
		model.addAttribute("raceYear",raceYear);
		model.addAttribute("raceName",raceName);
		model.addAttribute("raceId",raceId);

		List<Piloto> listaPilotos = new ArrayList<Piloto>();

		Boolean ok = true;

		/**
		 * Si por alguna razon no viene de la session alguno de esos 3 datos
		 * cancelo, porque me faltan datos Hago el llamado para obtener el PDF
		 * de las sesiones excepto resultados que lo voy a buscar a la pagina de
		 * la f1 El Hash esta puesto para guardar un unico resultado del pdf en
		 * la sesion y no haga tantos llamados
		 **/

		if (!StringUtils.isEmpty(raceRound) && !StringUtils.isEmpty(raceYear) && !StringUtils.isEmpty(raceName) && !StringUtils.isEmpty(raceId)) {
			pagina = "raceDetail";
			if (idSesion != null) {
				Sesiones sesion = Sesiones.valueOf(idSesion);
				model.addAttribute("SESION", sesion);
				String key = raceName + raceYear + sesion;
				if (!sesion.equals(Sesiones.RESULTS)) {
					ok = obtenerDatosSesiones(model, session, hashSesionLista, raceRound, raceYear, raceName, listaPilotos, ok, sesion, key, raceId);
				} else {
					ok = obtenerDatosResultados(model, request, session, hashSesionLista, raceRound, raceYear, raceName, raceId, key, ok);
				}
			} else {
				ok = false;
				model.addAttribute("ERROR", "No session selected.");
			}
		} else {
			ok = false;
			model.addAttribute("ERROR", "Some data are missing, please back to home and try again.");
		}

		model.addAttribute("OK", ok);
		return pagina;
	}
	
	@RequestMapping(value = "/compareDrivers", method = RequestMethod.POST)
	public String submitDriverCompare(Model model, HttpServletRequest request, HttpServletResponse response) {
		
		HttpSession session = request.getSession();
		
		if(session.getAttribute("HASHPILOTOS")!=null)
			session.removeAttribute("HASHPILOTOS");
		
		List<Piloto> listaPilotosFiltrada = new ArrayList<Piloto>();
		Boolean ok = true;
		
		try {
			String _listaPilotosElegidos = request.getParameter("driversSel");
			String[] listaPilotosElegidos = _listaPilotosElegidos.split(",");
			
			List<Piloto> listaPilotos  = (List<Piloto>) session.getAttribute("LISTAPILOTOS");
			
			for(String _numeroPiloto : listaPilotosElegidos){
				for(Piloto piloto : listaPilotos){
					if(piloto.getNumero() == Integer.parseInt(_numeroPiloto)){
						listaPilotosFiltrada.add(piloto);
						break;
					}
				}
			}
			model.addAttribute("LISTAPILOTOSFILTRADA", listaPilotosFiltrada);
			session.setAttribute("LISTAPILOTOSFILTRADA", listaPilotosFiltrada);
			pagina = "compareDrivers";
		} catch (Exception e) {
			e.printStackTrace();
			model.addAttribute("ERROR", "An error has ocurred, please try it later");
			ok=false;
		}
		
		model.addAttribute("OKCOMPARE", ok);
		return pagina;
	}
	
	private Boolean obtenerDatosResultados(Model model, HttpServletRequest request, HttpSession session, HashMap<String, Object> hashSesionLista, String raceRound, String raceYear, String raceName, String raceId, String key,Boolean ok) {
		Season season = (Season) session.getAttribute("SEASON-" + raceYear);
		if (season == null)
			season = (Season) session.getAttribute("season");

		List<ResultRace> resultadosCarreras = new ArrayList<ResultRace>();
		model.addAttribute("ERRORCARRERAS", false);

		try {
			if (hashSesionLista != null) {
				if (hashSesionLista.get(key) != null) {
					resultadosCarreras = (List<ResultRace>) hashSesionLista.get(key);
					model.addAttribute("RESULTADOCARRERAS", resultadosCarreras);
				} else {
					resultadosCarreras = LeerFIA.getResultadosCarrera(raceYear, raceRound, raceName, raceId);
					hashSesionLista.put(key, resultadosCarreras);
					model.addAttribute("RESULTADOCARRERAS", resultadosCarreras);
					session.setAttribute("HASHSESIONRESULTADO", hashSesionLista);
				}
			} else {
				hashSesionLista = new HashMap<String, Object>();
				resultadosCarreras = LeerFIA.getResultadosCarrera(raceYear, raceRound, raceName, raceId);
				hashSesionLista.put(key, resultadosCarreras);
				model.addAttribute("RESULTADOCARRERAS", resultadosCarreras);
				session.setAttribute("HASHSESIONRESULTADO", hashSesionLista);
			}
		} catch (Exception e) {
			if (e instanceof DescargarFormulaOneException) {
				model.addAttribute("ERROR", "Formula 1 website data for " + raceName + " is not available at this moment.");
				model.addAttribute("ERRORCARRERAS", true);
				ok = false;
			} else if (e instanceof DescargarFormulaOneParsingException) {
				model.addAttribute("ERROR", "Formula 1 website data for " + raceName + " cannot be parsed right now. Try it later");
				model.addAttribute("ERRORCARRERAS", true);
				ok = false;
			} else {
				model.addAttribute("ERROR", "An error has ocurred, please try it later");
				model.addAttribute("ERRORCARRERAS", true);
				ok = false;
			}
		}
		return ok;
	}

	private Boolean obtenerDatosSesiones(Model model, HttpSession session, HashMap<String, Object> hashSesionLista, String raceRound, String raceYear, String raceName, List<Piloto> listaPilotos, Boolean ok, Sesiones sesion, String key,String raceId) {
		long empezo = System.currentTimeMillis();
		try {
			if (hashSesionLista != null) {
				if (hashSesionLista.get(key) != null) {
					listaPilotos = (List<Piloto>) hashSesionLista.get(key);
					model.addAttribute("LISTAPILOTOS", listaPilotos);
					session.setAttribute("LISTAPILOTOS", listaPilotos);
				} else {
					listaPilotos = LeerPDF.leerPDF(raceRound, raceYear, raceName, sesion);
					hashSesionLista.put(key, listaPilotos);
					model.addAttribute("LISTAPILOTOS", listaPilotos);
					session.setAttribute("LISTAPILOTOS", listaPilotos);
					session.setAttribute("HASHSESIONRESULTADO", hashSesionLista);
				}
			} else {
				hashSesionLista = new HashMap<String, Object>();
				listaPilotos = LeerPDF.leerPDF(raceRound, raceYear, raceName, sesion);
				hashSesionLista.put(key, listaPilotos);
				model.addAttribute("LISTAPILOTOS", listaPilotos);
				session.setAttribute("LISTAPILOTOS", listaPilotos);
				session.setAttribute("HASHSESIONRESULTADO", hashSesionLista);
			}
		} catch (Exception e) {
			if (e instanceof DescargarFiaException) {
				model.addAttribute("ERROR", "FIA documents for " + raceYear + " " + raceName + " " + sesion + " are not available at this moment.");
				ok = false;
			} else if (e instanceof NoFileFiaException) {
				model.addAttribute("ERROR", "FIA documents for " + raceYear + " " + raceName + " " + sesion + " cannot be parsed right now. Try it later");
				ok = false;
			} else {
				model.addAttribute("ERROR", "An error has ocurred, please try it later");
				ok = false;
			}
		}
		log.info("Tiempo en procesar el PDF " + raceName + " | " + sesion + " : " + (System.currentTimeMillis() - empezo));
		return ok;
	}

}